package com.huangfuyi.process.actuator.definition;

import com.huangfuyi.process.actuator.threadpool.EPMainThreadPool;
import com.huangfuyi.process.entity.instance.EPInstanceEntity;
import com.huangfuyi.process.entity.mainthread.EPInstance;
import com.huangfuyi.process.entity.mainthread.EPSchedulerInfo;
import com.huangfuyi.process.entity.model.EPModelEntity;
import com.huangfuyi.process.entity.node.EPNodeEntity;
import com.huangfuyi.process.entity.node.EPNodeNextConfigEntity;
import com.huangfuyi.process.entity.running.EPParamEntity;
import com.huangfuyi.process.entity.running.EPRunningEntity;
import com.huangfuyi.process.entity.running.EPRunningWithParamsEntity;
import com.huangfuyi.process.managers.EPManagers;
import com.huangfuyi.process.managers.EPServiceManager;
import com.huangfuyi.process.service.EPCoreInstanceService;
import com.huangfuyi.process.service.EPCoreRunningService;

/**
 * 流程框架对接调度框架接口
 * 流程框架本身为单机运行框架，当流程框架与分布式调度框架对接后，可以实现分布式流程编排
 * 实现原理：
 * 流程框架的最小运行单位为流程节点，可以视为一个NodeApp接口的实现。
 * 当对接调度框架后，流程框架会将节点的运行信息提交给调度框架，
 * 然后调度框架在指定的调度时间使用该运行信息向流程框架发起调度，
 * 流程框架会立即根据运行信息执行对应的业务逻辑
 */
public abstract class EPScheduler {

    /**
     * 流程框架将节点运行信息交由调度框架的方法
     */
    public abstract void submit(EPSchedulerInfo schedulerConfig);

    /**
     * 流程框架取消节点调度任务的方法
     */
    public abstract void cancel(EPSchedulerInfo schedulerConfig);

    /**
     * 立即运行流程节点
     */
    public abstract void runNow(EPSchedulerInfo schedulerConfig);

    /**
     * 立即在当前节点上运行
     * */
    public final void runNowInCurrentNode(EPSchedulerInfo schedulerConfig) {
        EPServiceManager<? extends EPInstanceEntity, ? extends EPModelEntity, ? extends EPNodeEntity, ? extends EPNodeNextConfigEntity, ? extends EPRunningEntity, ? extends EPParamEntity> serviceManager = EPManagers.getServiceManager();
        EPCoreInstanceService<? extends EPInstanceEntity, ? extends EPModelEntity, ? extends EPNodeEntity, ? extends EPNodeNextConfigEntity, ? extends EPRunningEntity, ? extends EPParamEntity> instanceService = serviceManager.getInstanceService();

        EPInstanceEntity instanceEntity = instanceService.queryById(schedulerConfig.getInstanceId());

        EPCoreRunningService<? extends EPRunningEntity, ? extends EPParamEntity> runningService = serviceManager.getRunningService();
        EPRunningWithParamsEntity readyRunning = runningService.queryWithParamsById(schedulerConfig.getRunningId());

        EPInstance readyInstance = new EPInstance(instanceEntity.getId(), instanceEntity.getName(), instanceEntity.getModelId(), instanceEntity.getStatus(), readyRunning.getNodeId(), readyRunning.getId(), readyRunning.getParamsIn());
        EPMainThreadPool.execute(readyInstance);
    }

}
